using System;
using EPiServer.Common;
using EPiServer.Common.Cache;
using EPiServer.Common.Queries;

namespace EPiServer.Templates.RelatePlus.Templates.PageEntity
{
    public class PageEntityHandler
    {
        #region Cache Delegates
        internal delegate PageEntity GetPageEntityByIDDelegate(int id);
        internal delegate PageEntity GetPageEntityByGUIDDelegate(Guid guid);
        
        internal delegate PageEntityCollection GetPageEntityListDelegate();

        internal static GetPageEntityByIDDelegate _getPageEntityByIDDelegate = PageEntityFactory.GetPageEntity;
        internal static GetPageEntityByGUIDDelegate _getPageEntityByGUIDDelegate = PageEntityFactory.GetPageEntity;
        internal static GetPageEntityListDelegate _getPageEntityListDelegate =PageEntityFactory.GetPageEntities;

        internal const string TPR_LIST_CACHE_KEY = "PageEntityList";
        #endregion

        /// <summary>
        /// Gets the page entity by GUID.
        /// </summary>
        /// <param name="guid">The GUID.</param>
        /// <returns></returns>
        public static PageEntity GetPageEntityByGUID(Guid guid)
        {
            if (guid.Equals(Guid.Empty))
            {
                return null;
            }
            
            return (PageEntity)CacheHandler.GetCachedObject(_getPageEntityByGUIDDelegate,
                                                            new object[] { guid }, PageEntity.ConstructCacheKey(guid));
            
        }

        /// <summary>
        /// Gets the page reference entity.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public static PageEntity GetPageEntity(int id)
        {
            if (!EntityValidator.IsValidId(id))
                return null;

            return (PageEntity)CacheHandler.GetCachedObject(_getPageEntityByIDDelegate,
                                                            new object[] { id }, PageEntity.ConstructCacheKey(id));
        }

        /// <summary>
        /// Gets the page reference entities.
        /// </summary>
        /// <returns></returns>
        public static PageEntityCollection GetPageEntities()
        {
            return (PageEntityCollection)CacheHandler.GetCachedObject(_getPageEntityListDelegate,
                                                                      new object[0], "PageEntity", TPR_LIST_CACHE_KEY);
        }


        /// <summary>
        /// Adds the page entity.
        /// </summary>
        /// <param name="pageEntity">The page entity.</param>
        /// <returns></returns>
        public static PageEntity AddPageEntity(PageEntity pageEntity)
        {
            EntityValidator.ValidateIsNotNull(pageEntity, "pageEntity");

            PageEntity tpr = PageEntityFactory.AddPageEntity(pageEntity);
            CacheHandler.RemoveCachedObject("PageEntity", TPR_LIST_CACHE_KEY);
            return tpr;
        }

        /// <summary>
        /// Updates the page entity.
        /// </summary>
        /// <param name="pageEntity">The page entity.</param>
        public static void UpdatePageEntity(PageEntity pageEntity)
        {
            EntityValidator.ValidateIsCommittedEntity(pageEntity, "pageEntity");

            PageEntityFactory.UpdatePageEntity(pageEntity);

            CacheHandler.RemoveCachedObject(pageEntity);
        }


        /// <summary>
        /// Removes the page entity.
        /// </summary>
        /// <param name="pageEntity">The page entity.</param>
        public static void RemovePageEntity(PageEntity pageEntity)
        {
            EntityValidator.ValidateIsCommittedEntity(pageEntity, "pageEntity");

            PageEntityFactory.RemovePageEntity(pageEntity);

            CacheHandler.RemoveCachedObject(pageEntity);
        }

        /// <summary>
        /// Gets the query result.
        /// </summary>
        /// <param name="tprq">The TPRQ.</param>
        /// <returns></returns>
        public static PageEntityCollection GetQueryResult(PageEntityQuery tprq)
        {
            return (PageEntityCollection)QueryHandler.GetQueryResult<PageEntity, PageEntityCollection>(tprq);
        }
    }
}